package com.emmmya.ocs.filter;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.emmmya.ocs.config.xss.XssHttpServletRequestWrapper;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 防止XSS攻击的过滤器
 * 
 * @author xxx
 */
public class XssFilter implements Filter
{
    /**
     * 排除链接
     */
    public List<String> noFilterUrls = new ArrayList<>();

    /**
     * xss过滤开关
     */
    public boolean enabled = true;


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 从过滤器配置中获取initParams参数
        String noFilterUrl = filterConfig.getInitParameter("noFilterUrl");
        String enabledStr = filterConfig.getInitParameter("enabled");
        // 将排除的URL放入成员变量noFilterUrls中
        if (StringUtils.isNotBlank(noFilterUrl)) {
            noFilterUrls = new ArrayList<>(Arrays.asList(noFilterUrl.split(",")));
        }if(StringUtils.isNotBlank(enabledStr)){
            enabled = Boolean.valueOf(enabledStr);
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        if (!enabled || handleExcludeURL(req)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(req);
        filterChain.doFilter(xssRequest, servletResponse);
    }

    /**
     * 判断是否为忽略的URL
     * @return true-忽略，false-过滤
     */
    private boolean handleExcludeURL(HttpServletRequest request) {
        if (noFilterUrls == null || noFilterUrls.isEmpty()) {
            return false;
        }

        String url = request.getServletPath();
//        return excludes.stream().map(pattern -> Pattern.compile("^" + pattern)).map(p -> p.matcher(url))
//                .anyMatch(Matcher::find);
        for (String pattern : noFilterUrls) {
            pattern = pattern.replace("**", "*");
            Pattern p = Pattern.compile("^" + pattern);
            Matcher m = p.matcher(url);
            if (m.find()) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}